package edu.isistan.microops.rules;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

import org.drools.KnowledgeBase;
import org.drools.KnowledgeBaseFactory;
import org.drools.builder.KnowledgeBuilder;
import org.drools.builder.KnowledgeBuilderFactory;
import org.drools.builder.ResourceType;
import org.drools.definition.KnowledgePackage;
import org.drools.io.ResourceFactory;
import org.drools.runtime.StatefulKnowledgeSession;
import org.drools.runtime.rule.FactHandle;

import edu.isistan.microops.Mapping;
import edu.isistan.microops.MicroopsCalculator;


/**
 * 
 * @author 
 * Avellaneda, Juan Cruz 
 * Burgos, Agust�n 
 * Obregozo, Manuel
 * 
 * Esta clase encargada del manejo de las reglas, permite establecer la
 * sesion con el motor de reglas Drools, para su posterior consulta.
 * 
 */
public class RulesEngine {

	/**
	 * Esta variable indica la sesi�n que debe iniciarse, para poder acceder al
	 * motor de reglas
	 */
	private StatefulKnowledgeSession ksession;

	/**
	 * M�todo constructor donde se inicializa el motor de reglas, con el archivo
	 * .drl correpondiente que contiene las reglas que van a ser utilizadas y se
	 * establece la sesi�n con el mismo.
	 */

	public RulesEngine() {
		super();
		KnowledgeBuilder kbuilder = KnowledgeBuilderFactory
				.newKnowledgeBuilder();

		kbuilder.add(ResourceFactory.newUrlResource(RulesEngine.class
				.getResource("/resources/rules.drl")), ResourceType.DRL);
		
		

		if (kbuilder.hasErrors()) {
			System.out.println(kbuilder.getErrors().toString());
			throw new RuntimeException("Unable to compile \"rules.drl\".");
		}
		
		kbuilder.add(ResourceFactory.newUrlResource(RulesEngine.class
				.getResource("/resources/functions.drl")), ResourceType.DRL);
		
		if (kbuilder.hasErrors()) {
			System.out.println(kbuilder.getErrors().toString());
			throw new RuntimeException("Unable to compile \"functions.drl\".");
		}

		final Collection<KnowledgePackage> pkgs = kbuilder
				.getKnowledgePackages();

		final KnowledgeBase kbase = KnowledgeBaseFactory.newKnowledgeBase();
		kbase.addKnowledgePackages(pkgs);

		ksession = kbase.newStatefulKnowledgeSession();
		ksession.setGlobal("list", new ArrayList<String>());


		// Descomentar las siguientes lineas para que el motor de reglas
		// imprima por consola
		// ksession.addEventListener( new DebugAgendaEventListener() );
		// ksession.addEventListener( new DebugWorkingMemoryEventListener() );


		// Descomentar las siguientes lineas para usar FileLogger
		// KnowledgeRuntimeLogger logger =
		// KnowledgeRuntimeLoggerFactory.newFileLogger( ksession, "./helloworld"
		// );

		// Descomentar las siguientes lineas para usar ThreadedFileLogger
		// KnowledgeRuntimeLogger logger =
		// KnowledgeRuntimeLoggerFactory.newThreadedFileLogger( ksession,
		// "./helloworld", 1000 );

		// Descomentar las siguientes lineas se el logueo esta activado
		// logger.close();
	}

	/**
	 * 
	 * @param mCalc : Hecho (MicropsCalculator) que deseamos tratar.
	 * @return FactHnadle
	 * 
	 * Se inserta el Hecho, y retorna el Handler asociado al hecho
	 * insertado en el motor.
	 * 
	 */

	public FactHandle insertFact(Mapping m) {
		return ksession.insert(m);
	}

	/**
	 * 
	 * @param fHandle: Handler asociado al hecho que queremos quitar del motor.
	 * Quita el hecho del motor.
	 */
	public void retractFact(FactHandle fHandle) {
		ksession.retract(fHandle);
	}

	/**
	 * Realiza la consulta al motor de reglas, sobre los hechos que esten
	 * presentes en �l, contemplando cuales aplican al hecho a tratar.
	 */
	public void fireAllRules() {
		ksession.fireAllRules();
	}
}
